package application;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Scanner;

import domain.Game;
//import domain.Minimax;
import domain.Move;
//import domain.Node;
import domain.Player;
import domain.Position;
import domain.enums.GameStatus;

public class MagneticCave 
{
	
	private static Game game;
	
	/**
	 * @param args
	 */
	public static void main(String[] args) 
	{
		
		Scanner scanner;
		boolean isBlack;
	//	boolean isWhite;
		String gameOption;
		GameStatus gameStatus;
		
		boolean blackTurn = true;
		
		System.out.println("Welcome to Magnetic Cave!\n");
		
		do{
			System.out.println("Choose the following option: ");
			System.out.println("1. Manual entry for both Black and White players' moves (Enter 1)");
			System.out.println("2. Manual entry for Black's moves and automatic moves for White (Enter 2)");
			System.out.println("3. Automtic moves for Black, and manual entry for White (Enter 3)");
			scanner = new Scanner(System.in);
			gameOption = scanner.nextLine();
		}while(!(gameOption.equalsIgnoreCase("1") || gameOption.equalsIgnoreCase("2") || gameOption.equalsIgnoreCase("3")));
		
		isBlack = (gameOption.equalsIgnoreCase("1") || gameOption.equalsIgnoreCase("2"));
	//	isWhite = (gameOption.equalsIgnoreCase("1") || gameOption.equalsIgnoreCase("3"));
		

		game = new Game(!isBlack);
		System.out.println(game);
		
		
		do{
			turn(blackTurn, gameOption);
			blackTurn = !blackTurn;
			System.out.println(game);
			
		}while((gameStatus = game.getGameStatus()) == GameStatus.NO_WINNER);
		
		switch(gameStatus)
		{
		case B_WINS:
			System.out.println("Black won!");
			break;
		case W_WINS:
			System.out.println("White won!");
		}
		
		
		
		
		
		/**
		
		// TODO Auto-generated method stub
		Node root = new Node(null);

		//each parent has 2 children
		for (int i = 0; i < 2; i++)
		{
			Node c = new Node(root); //to know who are the parents
			
			for (int j = 0; j < 2; j++)
			{
				Node d = new Node(c);
				
				for (int k = 0; k < 2; k++)
				{
					Node e = new Node(d);
					e.setValue((int)Math.floor((Math.random()*10)+1));// random number btwn 1 - 10
					d.addChild(e);
					
					//System.out.print(e.getValue() + " ");
				}
				
				c.addChild(d);
			}
			
			root.addChild(c); // to know which is the children
		}
		
		//print initial tree
		System.out.println("\t    " + root.getValue());
		
		for (Node n1 : root.getChildren())
		{
			System.out.print("\t" + n1.getValue());
		}
		System.out.println("");
		for (Node n1 : root.getChildren().get(0).getChildren())
		{
			System.out.print(n1.getValue() + " \t");
		}
		for (Node n1 : root.getChildren().get(1).getChildren())
		{
			System.out.print(n1.getValue() + " \t");
		}
		
		System.out.println("");
		
		for (Node n1 : root.getChildren().get(0).getChildren().get(0).getChildren())
		{
			System.out.print(n1.getValue() + "   ");
		}
		for (Node n1 : root.getChildren().get(0).getChildren().get(1).getChildren())
		{
			System.out.print(n1.getValue() + "   ");
		}
		for (Node n1 : root.getChildren().get(1).getChildren().get(0).getChildren())
		{
			System.out.print(n1.getValue() + "   ");
		}
		for (Node n1 : root.getChildren().get(1).getChildren().get(1).getChildren())
		{
			System.out.print(n1.getValue() + "   ");
		}
	
		System.out.println();
		System.out.println();
		System.out.println();
		
		//apply minimax
		Minimax m = new Minimax(3, root); //current maxdept is 3
		System.out.println(m.getNextMove());
		
		//print resulted tree
		System.out.println("\t    " + root.getValue());
		
		for (Node n1 : root.getChildren())
		{
			System.out.print("\t" + n1.getValue());
		}
		System.out.println("");
		for (Node n1 : root.getChildren().get(0).getChildren())
		{
			System.out.print(n1.getValue() + " \t");
		}
		for (Node n1 : root.getChildren().get(1).getChildren())
		{
			System.out.print(n1.getValue() + " \t");
		}
		
		System.out.println("");
		
		for (Node n1 : root.getChildren().get(0).getChildren().get(0).getChildren())
		{
			System.out.print(n1.getValue() + "   ");
		}
		for (Node n1 : root.getChildren().get(0).getChildren().get(1).getChildren())
		{
			System.out.print(n1.getValue() + "   ");
		}
		for (Node n1 : root.getChildren().get(1).getChildren().get(0).getChildren())
		{
			System.out.print(n1.getValue() + "   ");
		}
		for (Node n1 : root.getChildren().get(1).getChildren().get(1).getChildren())
		{
			System.out.print(n1.getValue() + "   ");
		}
	
		System.out.println();
		System.out.println();
		System.out.println();
		
		**/
	}

	//whether it's Black's Turn, whether the manual player is Black
	/**
	 * @param bTurn
	 * @param playerIsBlack
	 */
	public static void turn(boolean bTurn, String gameOption)
	{
		Scanner scanner;
		
		if(bTurn)
		{
			if(gameOption.equalsIgnoreCase("2") || gameOption.equalsIgnoreCase("1")) //black's turn, black is manual
			{
				
				ArrayList<Player> blacks = game.getBlack();
				HashMap<String, Integer> blackPositions = new HashMap<String, Integer>();
				
				for(int i=0; i<blacks.size(); i++)
				{
					blackPositions.put(positionToString(blacks.get(i).getPosition()), i);
				}
				
				if(!blackPositions.keySet().isEmpty())
				{
					System.out.print("The Blacks are at these positions: ");
					for(String s : blackPositions.keySet())
					{
						System.out.print(s + " ");
					}
				}
				
				String input;
				
				do{
					System.out.println("\nEnter the coordinates you wish to add a new B: ");
					scanner = new Scanner(System.in);
					input = scanner.nextLine();
				}while( !( validInput(input) && game.validMove(new Move(bTurn, stringToPosition(input))) ));
			}
			else if(gameOption.equalsIgnoreCase("3"))//black's turn, black is the AI
			{
				Move move = game.getAIMove();
				System.out.println("A new B is added to: " + positionToString(move.getPosition()));
				if(!game.validMove(move))
					System.out.println("ERROR: Invalid AI move");
			}
			
		}
		else //white's turn
		{
			if(gameOption.equalsIgnoreCase("2")) //white turn, manual player is Black
			{
				Move move = game.getAIMove();
				System.out.println("A new W is added to: " + positionToString(move.getPosition()));
				if(!game.validMove(move))
					System.out.println("ERROR: Invalid AI move");
			}
			else if(gameOption.equalsIgnoreCase("3") || gameOption.equalsIgnoreCase("1")) //white's turn, manual entry for white
			{
				ArrayList<Player> whites = game.getWhite();
				HashMap<String, Integer> whitePositions = new HashMap<String, Integer>();
				
				for(int i=0; i<whites.size(); i++)
				{
					whitePositions.put(positionToString(whites.get(i).getPosition()), i);
				}
				
				if(!whitePositions.keySet().isEmpty())
				{
					System.out.print("The Whites are at these positions: ");
					for(String s : whitePositions.keySet())
					{
						System.out.print(s + " ");
					}
				}
				
				String input;
				
				do{
					System.out.println("\nEnter the coordinates you wish to add a new W: ");
					scanner = new Scanner(System.in);
					input = scanner.nextLine();
				}while( !( validInput(input) && game.validMove(new Move(bTurn, stringToPosition(input))) ));
			
			}
		}
	}
	
	private static Position stringToPosition(String input) 
	{
		input = input.toUpperCase();
		// convert first input character to ascii (A=65) and get corresponding board position
		int x = -(65 - (int)input.charAt(0));
		// get corresponding board position of second input character
		int y = game.getBoardWidth() - Integer.parseInt(input.substring(1, 2));

		return new Position(x, y);
	}

	public static boolean validInput(String input)
	{
		String pattern = "^([a-h]|[A-H])[1-8]$";
		return input.matches(pattern);
	}
	
	public static String positionToString(Position pos)
	{
		//to convert x-value to number, ascii code - A=65
		String x = new Character((char)(pos.getX() + 65)).toString();
		String y = String.valueOf(game.getBoardWidth() - pos.getY());
		return x + y;
	}
	
}
